using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia;
using Avalonia.VisualTree;
using DesktopApp.ViewModels;
using System;
using System.Diagnostics;

namespace DesktopApp.Views.Controls
{
    public partial class RuleManagementControl : UserControl
    {
        // Define a constant for the drag format
        public const string RuleItemDragFormat = "RuleItemViewModel";

        public RuleManagementControl()
        {
            InitializeComponent();

            // Find the ListBox by name and set SelectionMode programmatically
            var rulesListBox = this.FindControl<ListBox>("RulesListBox");
            if (rulesListBox != null)
            {
                rulesListBox.SelectionMode = Avalonia.Controls.SelectionMode.Multiple;
                Debug.WriteLine("[RuleManagementControl] SelectionMode set to Multiple programmatically.");
            }
            else
            {
                Debug.WriteLine("[RuleManagementControl] Error: RulesListBox not found in InitializeComponent.");
            }
        }

        // --- Drag and Drop Event Handlers ---

        private async void RulesListBox_PointerPressed(object? sender, PointerPressedEventArgs e)
        {
            // Find the ListBoxItem that was pressed
            var point = e.GetCurrentPoint(sender as Visual);
            if (point.Properties.IsLeftButtonPressed)
            {
                var visual = e.Source as Visual;
                ListBoxItem? listBoxItem = null;

                while (visual != null)
                {
                    if (visual is ListBoxItem item)
                    {
                        listBoxItem = item;
                        break;
                    }
                    visual = visual.GetVisualParent();
                }

                if (listBoxItem?.DataContext is RuleItemViewModel sourceRuleVm)
                {
                    Debug.WriteLine($"[RuleManagementControl] Starting drag for: {sourceRuleVm.Name}");
                    var dragData = new DataObject();
                    dragData.Set(RuleItemDragFormat, sourceRuleVm);
                    Debug.WriteLine($"[RuleManagementControl] Set drag data with format: '{RuleItemDragFormat}'");

                    try
                    {
                        var result = await DragDrop.DoDragDrop(e, dragData, DragDropEffects.Move);
                        Debug.WriteLine($"[RuleManagementControl] DragDrop finished with result: {result}");
                    }
                    catch (Exception ex)
                    {
                         Debug.WriteLine($"[RuleManagementControl] DragDrop exception: {ex.Message}");
                    }
                }
                else
                {
                     Debug.WriteLine("[RuleManagementControl] PointerPressed did not find RuleItemViewModel in DataContext.");
                }
            }
        }

        private void RulesScrollViewer_DragOver(object? sender, DragEventArgs e)
        {
            // Use the format observed in logs
            string observedFormat = "application/vnd.logclear.ruleitemviewmodel"; 
            Debug.WriteLine($"[RuleManagementControl] DragOver entered. Checking for format: '{observedFormat}'. Available: [{string.Join(", ", e.Data.GetDataFormats())}]");

            // Default to None
            e.DragEffects = DragDropEffects.None;

            // Allow drop only if the data is our expected format
            if (e.Data.Contains(observedFormat)) 
            {
                e.DragEffects = DragDropEffects.Move;
                Debug.WriteLine($"[RuleManagementControl] DragOver: Allowing Move (Format '{observedFormat}' found).");
            }
            else
            {
                Debug.WriteLine($"[RuleManagementControl] DragOver: Denying drop (Format '{observedFormat}' NOT found).");
                // Attempt to get data anyway for debugging
                var data = e.Data.Get(observedFormat);
                Debug.WriteLine($"[RuleManagementControl] DragOver: Data for format '{observedFormat}' is {(data == null ? "null" : "not null")}.");
            }
            e.Handled = true;
        }

        private void RulesScrollViewer_Drop(object? sender, DragEventArgs e)
        {
            if (sender is not Control dropTargetControl) return;
            if (this.DataContext is not RulesViewModel viewModel) return;

            // Use the format observed in logs
            string observedFormat = "application/vnd.logclear.ruleitemviewmodel";
            Debug.WriteLine($"[RuleManagementControl] Drop entered. Attempting to get data for format: '{observedFormat}'");
            if (e.Data.Get(observedFormat) is RuleItemViewModel sourceRuleVm)
            {
                Debug.WriteLine($"[RuleManagementControl] Drop: Successfully retrieved source RuleItemViewModel: {sourceRuleVm.Name}");
                // Find the target ListBoxItem under the drop position
                var dropPosition = e.GetPosition(dropTargetControl);
                ListBoxItem? targetListBoxItem = null;
                RuleItemViewModel? targetRuleVm = null;

                // Iterate through visuals under the pointer to find the ListBoxItem
                foreach (var visual in dropTargetControl.GetVisualsAt(dropPosition, v => v is ListBoxItem)) // More direct way
                {
                     if (visual is ListBoxItem item && item.DataContext is RuleItemViewModel vm && vm != sourceRuleVm) // Check if it's a ListBoxItem with the correct DataContext and not the source item itself
                    {
                        targetListBoxItem = item;
                        targetRuleVm = vm;
                        break;
                    }
                }

                // Determine drop position relative to the target item
                bool dropBefore = true; // Default to dropping before if no specific target found (e.g., drop in empty space at end) or if target found

                if (targetListBoxItem != null && targetRuleVm != null)
                {
                    var targetPosition = e.GetPosition(targetListBoxItem);
                    dropBefore = targetPosition.Y < (targetListBoxItem.Bounds.Height / 2);
                    Debug.WriteLine($"[RuleManagementControl] Drop target: {targetRuleVm.Name}, DropBefore: {dropBefore}");
                }
                else
                {
                    // Handle dropping in empty space (could be beginning or end)
                    // Let's default to dropping at the end if no target is found directly under cursor
                    // MoveRule handles null target as move to end.
                    targetRuleVm = null; 
                    Debug.WriteLine("[RuleManagementControl] Drop target not found, will attempt move to end.");
                }

                // Call the ViewModel method to move the rule
                Debug.WriteLine($"[RuleManagementControl] Calling MoveRule: Source='{sourceRuleVm.Name}', Target='{targetRuleVm?.Name ?? "null"}', DropBefore={dropBefore}");
                viewModel.MoveRule(sourceRuleVm, targetRuleVm, dropBefore);
            }
            else
            {
                 Debug.WriteLine("[RuleManagementControl] Drop failed: Could not retrieve source RuleItemViewModel.");
            }

            e.Handled = true;
        }

        // --- Drag Drop Logic specific to this control ---
        // If we want drag/drop contained here, move the handlers from MainWindow.axaml.cs
        // Otherwise, leave them in MainWindow as they might need broader context.
        // For now, let's assume MainWindow handles the drop events that need the RulesViewModel.

        // Example of moving DragOver here:
        // private void RulesScrollViewer_DragOver(object? sender, DragEventArgs e)
        // {
        //     // Allow drop only if the data is in the expected format
        //     if (e.Data.Contains(RuleItemView.RuleItemDragFormat))
        //     {
        //         e.DragEffects = DragDropEffects.Move;
        //     }
        //     else
        //     {
        //         e.DragEffects = DragDropEffects.None;
        //     }
        //     e.Handled = true;
        // }
    }
} 